﻿#if !defined(_ASTATE_H_)
#define _ASTATE_H_

#include "ATransition.h"

class ICAState
{
public:
    virtual int init() = 0;
    virtual int deinit() = 0;
    virtual int Enter(ccTime time) = 0;
    virtual int Update(ccTime time) = 0;
    virtual int Leave(ccTime time) = 0;
};

class CAMachine;
class CAState;
typedef CAStringMap<CAState> CAStates;

typedef enum enumStateEvent
{
	SE_StateNA,
	SE_StateNavigating = 10,
	SE_StateNavigated,
	SE_StateEntering,
	SE_StateEntered,
	SE_StateLeaving,
	SE_StateLeaved,
	//TransitionConditionConfirmed,
}
EStateEvent;

class CAStateEvent : public CAObject
{
protected:
	CAStateEvent()
	{
		sender = null;
		evt = SE_StateNA;
		param = null;
	}
public:
	virtual ~CAStateEvent() {}

    CAState* sender;
    EStateEvent evt;
    void* param;

	static CAStateEvent* create(CAState* s, EStateEvent e)
    {
		return create(s, e, null);
    }

    static CAStateEvent* create(CAState* s, EStateEvent e, void* p)
    {
		CAStateEvent* pe = new CAStateEvent();
        pe->sender = s;
        pe->evt = e;
        pe->param = p;
		//autorelease();
		return pe;
    }
	static const char* EStateEvent2String(EStateEvent se)
	{
	#define TEST_SE(a) if (se == SE_##a) return #a;
		TEST_SE(StateNavigating);
		TEST_SE(StateNavigated);
		TEST_SE(StateEntering);
		TEST_SE(StateLeaving);
		TEST_SE(StateEntered);
		TEST_SE(StateLeaved);
	#undef TEST_SE
		return "NA";
	}
};

class CAXMLNode;
class CAState : public CAObject, public ICAState
{
public:
    CAState(CAMachine* pmachine);
    virtual ~CAState();

protected:
	CAMachine* _machine;
public:
	inline CAMachine* getMachine() { return _machine; }
	//void setMachine(CAMachine* p);

protected:
    CAState* _parent;
public:
	inline const CAState* getParent() const { return _parent; }
	inline CAState* getParent() { return _parent; }
	inline void setParent(CAState* p) { _parent = p; }
	inline CAState* getLeafState()
	{
		if (null != _curstate) 
			return _curstate->getLeafState();
		else 
			return this;
	}
protected:
    CAString _name;
	CAString _desc;
public:
	inline CAString getName() const { return _name; }
	CAString getFullName() const;
	CAString getFullDesc() const;
protected:
	CAStates* _substates;
    CAState* _curstate;
    CAString _initstate;    
public:
	inline CAStates* getSubStates() { return _substates; }
    void collectAllStates(CAStates* states);
    void addState(CAState* ss);
    void removeState(CAState* ss);
	inline CAState* getCurState() { return _curstate; }
	void setCurState(CAState* ps);
	inline const CAString& getInitState() const	{return _initstate; }
	inline void setInitState(const CAString& init) { _initstate = init; }

    int getDeapth() const;

	void initialize(CAXMLNode* pnode);

	virtual int init();
	virtual int deinit();
protected:
	ccTime _timeEnter;
	ccTime _timeLeave;
	size_t _counter;
public:
	inline ccTime getTimeEnter() const { return _timeEnter; }
	inline ccTime getTimeLeave() const { return _timeLeave; }
public:
    virtual int Update(ccTime time);
    virtual int Enter(ccTime time);
	virtual int Leave(ccTime time);

protected:
	CCArray* _trans;
public:
	inline CCArray* getTrans() { return _trans; }
    inline void addTransition(CATransition* t) { _trans->addObject(t); }
    inline void removeTransition(CATransition* t) { _trans->removeObject(t); }
};

#endif //_ASTATE_H_


